package cn.moefly.json;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.time.Instant;


/**
 * 参考资料来源：https://blog.csdn.net/qq_42937522/article/details/110310826
 * 《SpringBoot 配置返回前端时间戳和接收时间戳自动转为LocalDateTime（前后端统一使用时间戳交互）》
 */
@Configuration
public class JacksonCustomizerConfig {


    /**
     * 这不是一个专门用于Jackson的转换器，
     * 但在这里注册了两个Long的前端返回转换
     * 注册了两个Instant的前端返回转换
     * 可以跟 {@link JacksonCustomizerConfig#jackson2ObjectMapperBuilderCustomizer()} 对比看一下
     * transfer long type to string type to prevent front-end error
     *
     * @return
     */
    @Bean
    public HttpMessageConverters customConverters() {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        // jackson
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(Instant.class, new InstantCustomSerializer());
        simpleModule.addDeserializer(Instant.class, new InstantCustomDeserializer());
        objectMapper.registerModule(simpleModule);

        // 创建使用该objectMapper
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return new HttpMessageConverters(new HttpMessageConverter[]{jackson2HttpMessageConverter});
    }


    /**
     * description:适配自定义序列化和反序列化策略，返回前端指定数据类型的数据
     * 猜测是 com.casa.aems.service.pico.config.BasicConfig#customConverters() 导致不生效
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            builder.serializerByType(Instant.class, new InstantCustomSerializer());
            builder.deserializerByType(Instant.class, new InstantCustomDeserializer());
        };
    }


    /**
     * description: Instance转换器，用于转换请求参数中的RequestParam和PathVariable参数
     * 接收毫秒级时间戳字符串——>LocalDateTime
     */
    @Bean
    public Converter<String, Instant> localDateTimeConverter() {

        return new Converter<String, Instant>() {
            @Override
            public Instant convert(String source) {
                return InstantCustomDeserializer.srtToInstant(source);
            }
        };
    }



}
